export async function combat(wujiang: any, enmy: any) {
  const zhandou = [] 
  let win: any
  class Warrior {
    name: any
    type: any
    atk: number
    iq: number
    def: number
    hp: number
    initialHp: number
    constructor(
      name: any,
      type: any,
      atk: number,
      iq: number,
      def: number,
      hp: number
    ) {
      this.name = name 
      this.type = type
      this.atk = atk 
      this.iq = iq 
      this.def = def 
      this.hp = hp 
      this.initialHp = hp
    }
    attack(target: { def: number; iq: number; hp: number; name: any }) {
      let damage: number
      if (this.type === '武将') {
        damage = Math.round(
          ((this.atk - target.def) * 0.02 +(this.hp/10)) *100 *(Math.random() * 0.1 + 0.95)
        )
        if (damage <= 0) damage = Math.floor(Math.random() * (15 - 1 + 1)) + 1
      } else if (this.type === '谋士') {
        damage = Math.round(
          ((this.iq - target.iq) * 0.02 + (this.hp/10)) *100 *(Math.random() * 0.1 + 0.95)
        )
        if (damage <= 0) damage = Math.floor(Math.random() * (15 - 1 + 1)) + 1
      }
      target.hp -= damage 
      if (target.hp <= 0) target.hp = 0
      zhandou.push(
        `${this.name} 攻击 ${target.name}，造成 ${damage} 点伤害，${target.name} 剩余 ${target.hp} 兵力。\n`
      )
      if (target.hp <= 0) {
        zhandou.push(`${target.name} 溃败。\n`)
        target.hp = 0
      }
    }
  }
  const result = wujiang.map(
    (wujiang: {
      name?: any
      type?: any
      atk?: any
      iq?: any
      def?: any
      hp?: any
    }) => {
      if (Object.keys(wujiang).length > 0) {
        return new Warrior(
          wujiang.name,
          wujiang.type,
          wujiang.atk,
          wujiang.iq,
          wujiang.def,
          wujiang.hp
        )
      } else {
        return null
      }
    }
  )
  const diren = enmy.map(wujiang => {
    if (Object.keys(wujiang).length > 0) {
      return new Warrior(
        wujiang.name,
        wujiang.type,
        wujiang.atk,
        wujiang.iq,
        wujiang.def,
        wujiang.hp
      )
    } else {
      return null
    }
  })
  class Team {
    name: string
    warriors: any
    currentWarriorIndex: number
    constructor(name: string, warriors: any) {
      this.name = name 
      this.warriors = warriors 
      this.currentWarriorIndex = -1 
    }
    getNextWarrior() {
      let nextIndex = this.currentWarriorIndex + 1
      while (
        nextIndex < this.warriors.length &&
        (!this.warriors[nextIndex] || this.warriors[nextIndex].hp <= 0)
      ) {
        nextIndex++
      }
      if (nextIndex >= this.warriors.length) {
        nextIndex = 0
        while (
          nextIndex < this.warriors.length &&
          (!this.warriors[nextIndex] || this.warriors[nextIndex].hp <= 0)
        ) {
          nextIndex++
        }
      }
      if (!this.warriors[nextIndex]) return null
      this.currentWarriorIndex = nextIndex
      return this.warriors[nextIndex]
    }
    isDefeated() {
      return !this.warriors[4] || this.warriors[4].hp <= 0
    }
  }
  const teamA = new Team('甲', result)
  const teamB = new Team('乙', diren)
  let totalLossA = 0
  let totalLossB = 0
  function battle(teamA, teamB) {
    let round = 1
    while (!teamA.isDefeated() && !teamB.isDefeated()) {
      zhandou.push(`第${round}回合：\n`)
      const warriorA = teamA.getNextWarrior() 
      const warriorB = teamB.getNextWarrior() 
      let attackPriorityA, attackPriorityB
      switch (teamA.currentWarriorIndex) {
        case 0:
        case 3:
        case 6:
          attackPriorityA = [2, 5, 8, 1, 4, 7]
          break
        case 2:
        case 5:
        case 8:
          attackPriorityA = [0, 3, 6, 1, 4, 7]
          break
        case 1:
        case 4:
        case 7:
          attackPriorityA = [1, 4, 7]
          break
      }
      switch (teamB.currentWarriorIndex) {
        case 0:
        case 3:
        case 6:
          attackPriorityB = [2, 5, 8, 1, 4, 7]
          break
        case 2:
        case 5:
        case 8:
          attackPriorityB = [0, 3, 6, 1, 4, 7]
          break
        case 1:
        case 4:
        case 7:
          attackPriorityB = [1, 4, 7]
          break
      }
      let targetA = null,
        targetB = null
      for (let i = 0; i < attackPriorityA.length; i++) {
        if (
          teamB.warriors[attackPriorityA[i]] &&
          teamB.warriors[attackPriorityA[i]].hp > 0
        ) {
          targetA = teamB.warriors[attackPriorityA[i]]
          break
        }
      }
      for (let i = 0; i < attackPriorityB.length; i++) {
        if (
          teamA.warriors[attackPriorityB[i]] &&
          teamA.warriors[attackPriorityB[i]].hp > 0
        ) {
          targetB = teamA.warriors[attackPriorityB[i]]
          break
        }
      }
      if (warriorA && warriorA.hp > 0) warriorA.attack(targetA) 
      if (teamB.isDefeated()) break 
      if (warriorB && warriorB.hp > 0) warriorB.attack(targetB) 
      if (teamA.isDefeated()) break 
      round++
    }
    zhandou.push(
      `${teamA.isDefeated() ? teamB.name : teamA.name} 获得了胜利！\n` 
    )
    const sheng = teamA.isDefeated() ? teamB.name : teamA.name

    for (let i = 0; i < wujiang.length; i++) {
      if (wujiang[i].name) {
        wujiang[i].hp = teamA.warriors[i].hp
      }
    }
    for (let i = 0; i < enmy.length; i++) {
      if (enmy[i].name) {
        enmy[i].hp = teamB.warriors[i].hp
      }
    }
    if (sheng == '甲') {
      win = 'playerwin'
    } else if (sheng == '乙') {
      win = 'enmywin'
    }
  }
  battle(teamA, teamB)

  totalLossA = teamA.warriors.reduce((total, warrior) => {
    if (warrior) {
      const loss = warrior.initialHp - warrior.hp
      total += Math.max(0, loss)
    }
    return total
  }, 0)

  totalLossB = teamB.warriors.reduce((total, warrior) => {
    if (warrior) {
      const loss = warrior.initialHp - warrior.hp
      total += Math.max(0, loss)
    }
    return total
  }, 0)

  return {
    win: win,
    hp: wujiang.map(warrior => warrior.hp),
    dihp: enmy.map(warrior => warrior.hp),
    zhandou: zhandou,
    md: totalLossA,
    dimd: totalLossB
  }
}
